﻿using SharpDX.DirectSound;
using SharpDX.Multimedia;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using FragLabs.Audio.Codecs;
using System.IO;

namespace PeerComLink
{
    class AudioCaptureController
    {
        AutoResetEvent _autoResetEvent;
        int _bufferSize;
        CaptureBuffer _captureBuffer;
        OpusEncoder _opusEnc;

        public AudioCaptureController()
        {
            DirectSoundCapture capture = new DirectSoundCapture();

            WaveFormat waveFormat = WaveFormat.CreateCustomFormat(WaveFormatEncoding.Pcm,
                App.WaveFormatParams.SamplesPerSecond, App.WaveFormatParams.Channels,
                App.WaveFormatParams.AverageBytesPerSecond, App.WaveFormatParams.BlockAlign,
                App.WaveFormatParams.BitsPerSample);



            CaptureBufferDescription captureBufferDescription = new CaptureBufferDescription();
            _bufferSize = captureBufferDescription.BufferBytes = waveFormat.ConvertLatencyToByteSize(20) * 2;
            captureBufferDescription.Format = waveFormat;

            _captureBuffer = new CaptureBuffer(capture, captureBufferDescription);

            CreateNotifyPositions();

            _captureBuffer.Start(true);

            
            _opusEnc = OpusEncoder.Create(App.WaveFormatParams.SamplesPerSecond, App.WaveFormatParams.Channels, FragLabs.Audio.Codecs.Opus.Application.Voip);

        }
        int _bufferOffsetSection = 0;
        internal byte[] ReadData()
        {
            byte[] outputBuffer = new byte[_bufferSize / 2];
            int bufferOffset = _bufferOffsetSection++ * (_bufferSize / 2);
            _bufferOffsetSection = _bufferOffsetSection > 1 ? 0 : _bufferOffsetSection;

            _autoResetEvent.WaitOne();
            _captureBuffer.Read<byte>(outputBuffer, 0, _bufferSize / 2, bufferOffset, LockFlags.None);
            //return outputBuffer;

            int encodedLength;
            byte[] encodedData = _opusEnc.Encode(outputBuffer, outputBuffer.Length, out encodedLength);
            byte[] encodedDataToSend = new byte[encodedLength];
            Buffer.BlockCopy(encodedData, 0, encodedDataToSend, 0, encodedLength);
            return encodedDataToSend;
        }

        private void CreateNotifyPositions()
        {
            try
            {
                _autoResetEvent = new AutoResetEvent(false);
                NotificationPosition bufferPositionNotify1 = new NotificationPosition();
                bufferPositionNotify1.Offset = _bufferSize / 2 - 1;
                bufferPositionNotify1.WaitHandle = _autoResetEvent;

                NotificationPosition bufferPositionNotify2 = new NotificationPosition();
                bufferPositionNotify2.Offset = _bufferSize - 1;
                bufferPositionNotify2.WaitHandle = _autoResetEvent;

                _captureBuffer.SetNotificationPositions(new NotificationPosition[] { bufferPositionNotify1, bufferPositionNotify2 });
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "VoiceChat-CreateNotifyPositions ()", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
}
